package ink.mint.matrix;

/**
 * 矩阵接口
 */
public interface Matrixable {

    /**
     * 随机向量
     *
     * @param row 向量行
     * @return 一个随机向量
     */
    double[] random(int row);

    /**
     * 随机矩阵
     *
     * @param row    矩阵的行数
     * @param column 矩阵的列数
     * @return 一个随机矩阵
     */
    double[][] random(int row, int column);

    /**
     * 零向量
     *
     * @param row 向量的行
     * @return 一个零向量
     */
    double[] zero(int row);

    /**
     * 零矩阵
     *
     * @param row    矩阵的行
     * @param column 矩阵的列
     * @return 一个零矩阵
     */
    double[][] zero(int row, int column);

    /**
     * one-hot 编码
     *
     * @param number         数字
     * @param dimensionality 维度
     * @return [0, 0, 0, 1, 0, 0....., 0, 0]
     */
    double[] oneHotEncoding(int number, int dimensionality);

    /**
     * 自定义数的向量（所有元素相同）
     *
     * @param customNumber 自定义数
     * @return 自定义数的向量（所有元素相同）
     */
    double[] customNumber(double customNumber, int row);

    /**
     * 自定义数的矩阵（所有元素相同）
     *
     * @param customNumber 自定义数
     * @return 自定义数的矩阵（所有元素相同）
     */
    double[][] customNumber(double customNumber, int row, int column);

    /**
     * 矩阵转置
     *
     * @param A 矩阵A
     * @return 转置矩阵
     */
    double[][] transpose(double[][] A);

    /**
     * 列向量转变一行矩阵
     *
     * @param A 向量
     * @return 单行矩阵{{1,2,3...}}
     */
    double[][] vectorToRowMatrix(double[] A);

    /**
     * 列向量转变一行多列矩阵
     *
     * @param A 向量
     * @return 单行多列矩阵{{1},{2},{3}...}
     */
    double[][] vectorToColumnMatrix(double[] A);

    /**
     * 一行矩阵变向量
     *
     * @param A 单行矩阵
     * @return 向量
     */
    double[] matrixToVector(double[][] A);

    /**
     * 向量最大值索引
     *
     * @param A 向量
     * @return 向量的最大值的索引
     */
    int maxVectorIndex(double[] A);

    /**
     * 向量取反
     *
     * @param A 向量A
     * @return 反向量
     */
    double[] not(double[] A);


    /**
     * 向量绝对值
     *
     * @param A 向量A
     * @return 绝对值向量
     */
    double[] abs(double[] A);

    /**
     * 矩阵绝对值
     *
     * @param A 矩阵A
     * @return 绝对值矩阵
     */
    double[][] abs(double[][] A);

    /**
     * 向量总和
     *
     * @param A 向量A
     * @return 向量的总和  一个标量
     */
    double vectorSum(double[] A);

    /**
     * log 自定义向量
     *
     * @param A    向量A
     * @param base log的底数
     * @return 以base为底的log向量
     */
    double[] log(double[] A, double base);

    /**
     * log 自定义矩阵
     *
     * @param A    矩阵A
     * @param base log的底数
     * @return 以base为底的log矩阵
     */
    double[][] log(double[][] A, double base);

    /**
     * ln向量
     *
     * @param A 向量A
     * @return ln向量 以e为底的自然对数
     */
    double[] ln(double[] A);

    /**
     * ln矩阵
     *
     * @param A 矩阵A
     * @return ln矩阵 以e为底的自然对数
     */
    double[][] ln(double[][] A);

    /**
     * 一个数减向量
     *
     * @param number 一个数
     * @param A      向量A
     * @return 被一个数减去的向量
     */
    double[] sub(double number, double[] A);

    /**
     * 向量减去一个数
     *
     * @param A      向量A
     * @param number 一个数
     * @return 向量减去一个数
     */
    double[] sub(double[] A, double number);

    /**
     * 向量除法
     *
     * @param A 向量A
     * @param B 向量B
     * @return 向量被除结果
     */
    double[] division(double[] A, double[] B);

    /**
     * 矩阵除法
     *
     * @param A 矩阵A
     * @param B 矩阵B
     * @return 矩阵各元素被除结果
     */
    double[][] division(double[][] A, double[][] B);

    /**
     * 向量加法
     *
     * @param A 向量A
     * @param B 向量B
     * @return 向量的和
     */
    double[] add(double[] A, double[] B);

    /**
     * 矩阵加法
     *
     * @param A 矩阵A
     * @param B 矩阵B
     * @return 矩阵的和
     */
    double[][] add(double[][] A, double[][] B);

    /**
     * 向量减法
     *
     * @param A 向量A
     * @param B 向量B
     * @return 向量的差
     */
    double[] sub(double[] A, double[] B);

    /**
     * 矩阵的减法
     *
     * @param A 矩阵A
     * @param B 矩阵B
     * @return 矩阵的差
     */
    double[][] sub(double[][] A, double[][] B);

    /**
     * 向量元素点积
     *
     * @param A 向量A
     * @param B 向量B
     * @return 向量元素点积
     */
    double[] elementProduct(double[] A, double[] B);


    /**
     * 矩阵元素点积
     *
     * @param A 矩阵A
     * @param B 矩阵B
     * @return 矩阵元素点积
     */
    double[][] elementProduct(double[][] A, double[][] B);

    /**
     * 向量的幂
     *
     * @param A      向量A
     * @param number 幂
     * @return 向量的幂
     */
    double[] pow(double[] A, double number);

    /**
     * 向量乘以一个数
     *
     * @param A      向量A
     * @param number 一个数
     * @return 向量乘以一个数
     */
    double[] multi(double[] A, double number);

    /**
     * 向量求和
     *
     * @param A 向量A
     * @return 向量的值的总和
     */
    double sum(double[] A);

    /**
     * 矩阵求和
     *
     * @param A 矩阵A
     * @return 矩阵的值的总和
     */
    double sum(double[][] A);

    /**
     * 矩阵压缩为一维向量
     *
     * @param A 矩阵A
     * @return 矩阵A压缩后的一维向量
     */
    double[] matrixSumToVector(double[][] A);

    /**
     * 矩阵的幂
     *
     * @param A      矩阵A
     * @param number 幂
     * @return 矩阵的幂
     */
    double[][] pow(double[][] A, double number);

    /**
     * 矩阵乘以一个数
     *
     * @param A      矩阵A
     * @param number 一个数
     * @return 矩阵乘以一个数
     */
    double[][] multi(double[][] A, double number);

    /**
     * 矩阵的乘法
     *
     * @param A 矩阵A
     * @param B 矩阵B
     * @return 两个矩阵的积
     */
    double[][] multi(double[][] A, double[][] B);

    /**
     * 将一个数二值化
     *
     * @param A                    一个数
     * @param binarizationInterval 二值化（0到某个值的区间内）
     * @return 二值化的数
     */
    double binarization(double A, double binarizationInterval);

    /**
     * 将向量二值化
     *
     * @param A                    向量A
     * @param binarizationInterval 二值化（0到某个值的区间内）
     * @return 二值化的向量
     */
    double[] binarization(double[] A, double binarizationInterval);

    /**
     * 将矩阵二值化
     *
     * @param A                    矩阵A
     * @param binarizationInterval 二值化（0到某个值的区间内）
     * @return 二值化的矩阵
     */
    double[][] binarization(double[][] A, double binarizationInterval);

    /**
     * 将矩阵所有元素加和位标量
     *
     * @param A 矩阵A
     * @return 所求的矩阵标量
     */
    double matrixSum(double[][] A);
}
